package com.lifesting;

import java.math.BigInteger;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.classic.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.lifesting.front.Column;
import com.lifesting.front.FacesUtil;
import com.lifesting.front.Table;

public final class HbUtil {
	private static final SessionFactory sessionFactory;
	static {
		try {
			sessionFactory = new AnnotationConfiguration().configure()
					.buildSessionFactory();
		} catch (Throwable ex) {
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	// 获得总记录数，filter将采用like '%filter%'
	public static Integer getTotalCount(String beanname, String filterField,
			String filterLike) {
		Session session = getSessionFactory().openSession();
		try {
			Criteria countQuery = session.createCriteria(Class
					.forName(FacesUtil.getQualifiedName(beanname)));
			if (filterField != null) {
				countQuery.add(Restrictions.like(filterField, filterLike,
						MatchMode.START));
			}
			countQuery.setProjection(Projections.rowCount());
			return (Integer) countQuery.uniqueResult();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return 0;
	}

	public static List getRowsData(Table table) {
		Session session = getSessionFactory().openSession();
		try {
			Criteria pageDataQuery = session.createCriteria(Class
					.forName(FacesUtil.getQualifiedName(table.getBeanName())));
			if (table.getFilterField() != null) {
				pageDataQuery.add(Restrictions.like(table.getFilterField(),
						table.getFilterLike(), MatchMode.START));
			}
			List<Column> columns = FacesUtil.getColumn(table);
			for (Iterator<Column> ci = columns.iterator(); ci.hasNext();) {
				Column c = ci.next();
				if (c.getSortOrder() != Column.NON_SORT && c.getEnableSorter()) {
					if (c.getSortOrder() == Column.ASC_SORT) {
						pageDataQuery.addOrder(Order.asc(c.getField()));
					} else {
						pageDataQuery.addOrder(Order.desc(c.getField()));
					}
				}
			}
			pageDataQuery.setFirstResult((table.getCurrentPage() - 1)
					* table.getRowsCount());
			pageDataQuery.setMaxResults(table.getRowsCount());
			return pageDataQuery.list();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return Collections.EMPTY_LIST;

	}

	public static int deleteRows(FacesContext context, Table tb, String[] ids) {
		Session session = getSessionFactory().openSession();
		int total = 0;
		Transaction trans = session.beginTransaction();
		try {
			String fqn = FacesUtil.getQualifiedName(tb.getBeanName());
			Query delete_query = session.createQuery("delete from " + fqn
					+ " where "+tb.getIdField()+"=:id");
			Class field_type = Class.forName(fqn).getDeclaredField(tb.getIdField()).getType() ;
			if (!supportType(field_type)){
				throw new HibernateException("不支持的Hibernate类唯一标识类型: "+field_type.getName()+" (int/long/bigint/biglong)");
			}
			for (int i = 0; i < ids.length; i++) {
				Object id_object = getTargetObject(field_type,ids[i]);
				delete_query.setParameter("id",id_object);
				total += delete_query.executeUpdate();
			}
			trans.commit();
		} catch (HibernateException e) {// 给jsf页面显示一个错误信息？
			trans.rollback();
			FacesMessage msg = new FacesMessage();
			msg.setSeverity(FacesMessage.SEVERITY_ERROR);
			msg.setSummary("出错啦:" + e.getLocalizedMessage());
			context.addMessage(tb.getClientId(context), msg);
			throw e;
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return total;
	}
	public static final Class[] SUPPORTED = {Integer.class, Long.class, BigInteger.class, BigInteger.class, String.class};
	private static Object getTargetObject(Class field_type, String string) {
		if (field_type == Integer.class) return Integer.valueOf(string);
		else if (field_type == Long.class) return Long.valueOf(string);
		else if (field_type == BigInteger.class) return new BigInteger(string);
		else if (field_type == String.class) return string;
		else throw new NullPointerException("Impossible!~");
	}

	//暂时只支持整数和字符两种类型
	private static boolean supportType(Class field_type) {
		for (int i = 0; i < SUPPORTED.length; i++)
		{
			if (SUPPORTED[i] == field_type)
			{
				return true;
			}
		}
		return false;
	}
}
